闲话 22.12.10
闲话
今日闲话写一部分发一部分(
所以常来看看!
还是杂题(
题面长,不粘。
首先有一个观察是 、、 这三段可以分开考虑贡献再合并。
容易发现 这一段对答案的贡献是 ,由于没有限制。
随后考虑前两个部分如何计算。
首先可以发现,从第二行开始,每一行的积木数量都落在一个区间 内。我们尝试生成积木数量的计数。首先设 。不难得到第 行的生成函数为 。
我们发现目前的生成函数的最低项是非常数项。不妨将系数进行偏移,令 ,第 行的生成函数为 ,这样 对应的就是第 行放 个积木的计数了。
然后可以枚举 表示第 行积木数量偏移后为 的计数,并以此生成第 行积木数量偏移后的值 。我们可以将 进行二次偏移,随后提取 的第 项系数。
依照上方描述,有 。
前两部分的答案就是
你可能要问了:上界呢?
求和的上界是偏移后的上界,也就是 最高的度数。 的度数最大是 ,在自乘最多 次后得到求和上界 。
发现 最高可能达到 的范围,直接做 NTT 的复杂度是 ,显然过不去。
你问怎么做?我们发现对 的操作只有求幂运算,不难想到首先将 进行 DFT 后对点值求幂,再 IDFT 回来。这样就三次 DFT 得到答案。
code
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (register int i = (a), i##_ = (b) + 1; i < i##_; ++i)
#define pre(i,a,b) for (register int i = (a), i##_ = (b) - 1; i > i##_; --i)
const int N = 2e7 + 10, mod = 998244353, g = 3;
int n, www, l, r, x, y, z, A[N], B[N], ans;
int qp(int a, int b) {
int ret = 1;
while (b) {
if (b & 1) ret = 1ll * ret * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
} return ret;
}
int btrs[N];
int initrs(int k) {
int len = 1; while (len < k) len <<= 1;
for (int i = 0; i < len; ++ i)
btrs[i] = (btrs[i >> 1] >> 1) | ((i & 1) ? len >> 1 : 0);
return len;
}
const int L = 1 << 21;
int w[2][L];
int IUR() {
w[0][0] = w[1][0] = 1;
int w0 = qp(g, (mod - 1) / L);
for (int i = 1; i < L; ++ i) w[0][L - i] = w[1][i] = 1ll * w[1][i-1] * w0 % mod;
return 1;
} int dummy = IUR();
void NTT(int A[], int len, int type) {
for (int i = 0; i < len; ++ i) if (i < btrs[i]) swap(A[i], A[btrs[i]]);
for (int mid = 1; mid < len; mid <<= 1) {
for (int i = L / (mid << 1), j = 0; j < len; j += (mid << 1)) {
for (int k = 0; k < mid; ++ k) {
int x = A[j + k], y = 1ll * A[j + k + mid] * w[type][i * k] % mod;
A[j + k] = (x + y) % mod;
A[j + k + mid] = (x - y + mod) % mod;
}
}
} if (type == 1) return ;
int tmp = qp(len, mod - 2);
for (int i = 0; i < len; ++ i) A[i] = 1ll * A[i] * tmp % mod;
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> www >> l >> r >> x >> y >> z;
int len = n * (r - l) + 1, lim = initrs(len);
rep(i,0,r - l) A[i] = 1;
NTT(A, lim, 1);
for (int i = 0; i < lim; ++ i) B[i] = qp(A[i], y - x), A[i] = qp(A[i], x - 1);
NTT(A, lim, 0), NTT(B, lim, 0);
for (int i = 0, p; i < len; ++ i) {
p = z * (www + (x - 1) * l + i) - (www + (y - 1) * l + i);
if (p < 0) continue; if (p >= lim) break;
ans = (ans + 1ll * A[i] * B[p]) % mod;
} cout << 1ll * ans * qp(r - l + 1, n - y) % mod;
}
多项式的次数无法降低,我们就需要寻找一种方法递推出它的系数。
不妨考虑较广泛的情况,即递推
的前 项系数。
通过与P5434类似的手法,我们可以得到
即
这自然导出了递推方案。因此可以做到 递推。
统计答案并非瓶颈,因此做到了 求解本题。
code
常数有点大,目前是 lg 最劣解(
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (register int i = (a), i##_ = (b) + 1; i < i##_; ++i)
#define pre(i,a,b) for (register int i = (a), i##_ = (b) - 1; i > i##_; --i)
const int N = 2e7 + 10, mod = 998244353, g = 3;
int n, www, l, r, x, y, z, A[N], B[N], ans, len, lim;
int inv[N];
int qp(int a, int b) {
int ret = 1;
while (b) {
if (b & 1) ret = 1ll * ret * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
} return ret;
}
void get(int f[], int n, int m) {
f[0] = 1;
rep(i,1,len) {
f[i] = f[i - 1];
if (i - n + 1 >= 0) f[i] = (f[i] - 1ll * n * f[i - n] % mod + mod) % mod;
if (i - n >= 0) f[i] = (f[i] + 1ll * (n - 1) * f[i - n - 1]) % mod;
f[i] = 1ll * f[i] * m % mod;
if (i - 1 >= 0) f[i] = (f[i] + 1ll * (i - 1) * f[i - 1]) % mod;
if (i - n >= 0) f[i] = (f[i] + 1ll * (i - n) * f[i - n]) % mod;
if (i - n - 1 >= 0) f[i] = (f[i] - 1ll * (i - n - 1) * f[i - n - 1] % mod + mod) % mod;
f[i] = 1ll * f[i] * inv[i] % mod;
}
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> www >> l >> r >> x >> y >> z;
len = n * (r - l) + 1;
inv[0] = inv[1] = 1;
rep(i,2,len) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
get(A, r - l + 1, x - 1);
get(B, r - l + 1, y - x);
for (int i = 0, p; i < len; ++ i) {
p = z * (www + (x - 1) * l + i) - (www + (y - 1) * l + i);
if (p < 0) continue; if (p >= len) break;
ans = (ans + 1ll * A[i] * B[p]) % mod;
} cout << 1ll * ans * qp(r - l + 1, n - y) % mod;
}
流题
你是数学题吧?!一定是的对吧!
其实答案可以被写成
形如这样的式子都可以被表示为最小割。我们看 为选择了 与否的布尔型,考虑22.12.8最后一题的手法,选一条边表示选择这条边对应的状态。那状态如何设计呢?
我们仍然建 个点,与源点连接表示不选,与汇点连接表示选。那自然可以连汇点的流是 ,不连源点(流是 )。随后考虑当不一定都选择,即 至少有一条边连向了汇点的情况。这时拿一个新节点从源点连在 上即可。我们必须要割掉源点到新节点的边。
注意是和减去最小割。
code
int M, s, t, n, m, ans, id[505][505];
int b[505][505], c[505];
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
rep(i,1,n) rep(j,1,n) cin >> b[i][j], ans += b[i][j];
rep(i,1,n) cin >> c[i];
M = n; s = ++ M, t = ++ M;
rep(i,1,n) if (c[i] > 0) {
adde(i, t, c[i]);
}
int t1, t2, t3;
rep(i,1,n) rep(j,1,n) if(b[i][j] > 0) {
t1 = i, t2 = j, t3 = ++ M;
adde(s, t3, b[i][j]);
adde(t3, t1, inf);
adde(t3, t2, inf);
}
cout << ans - Dinic(s, t);
}
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/chitchat221210.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)